﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using DevExpress.Xpo;
using DevExpress.ExpressApp.Security;
using System.Security.Permissions;
using DevExpress.ExpressApp.Editors;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.Base.Security;
using DevExpress.ExpressApp.Filtering;
using DevExpress.Data.Filtering.Helpers;
using DevExpress.ExpressApp;
using System.ComponentModel;
using DevExpress.ExpressApp.DC;
using System.Diagnostics;

namespace CRMSolution.Module
{
    /// <summary>
    /// 成员操作，含没有设置、读、写，指要控制的权限的动作
    /// </summary>
    public enum MemberOperation { NotAssigned, Read, Write }
    /// <summary>
    /// 成员存取权限项目
    /// </summary>
    public class MemberAccessPermissionItem
    {

        private string memberName;

        private Type objectType;

        private MemberOperation operation;

        private ObjectAccessModifier modifier;

        public MemberAccessPermissionItem() { }
        /// <summary>
        /// 构造,相当于克隆
        /// </summary>
        /// <param name="source"></param>
        public MemberAccessPermissionItem(MemberAccessPermissionItem source)
        {
            this.memberName = source.memberName;
            this.objectType = source.objectType;
            this.operation = source.operation;
            this.modifier = source.modifier;
        }
        /// <summary>
        /// 成员类型
        /// </summary>
        public Type ObjectType
        {
            get { return objectType; }
            set { objectType = value; }
        }
        /// <summary>
        /// 成员（属性、字段）名称
        /// </summary>
        public string MemberName
        {
            get { return memberName; }
            set { memberName = value; }
        }
        /// <summary>
        /// 操作
        /// </summary>
        public MemberOperation Operation
        {
            get { return operation; }
            set { operation = value; }
        }
        /// <summary>
        /// 权限,如，允许、禁止、没有设置
        /// </summary>
        public ObjectAccessModifier Modifier
        {
            get { return modifier; }
            set { modifier = value; }
        }
    }

    /// <summary>
    /// 成员存取权限，应该是显示在新建菜单上的
    /// </summary>
    [NonPersistent]
    public class MemberAccessPermission : PermissionBase
    {
        private List<MemberAccessPermissionItem> items = new List<MemberAccessPermissionItem>();

        /// <summary>
        /// 取设置模式结点
        /// </summary>
        /// <returns></returns>
        private MemberAccessPermissionItem GetDesignModeItem()
        {
            if (items.Count > 1)
            {
                throw new InvalidOperationException();
            }
            if (items.Count == 0)
            {
                items.Add(new MemberAccessPermissionItem());
            }
            return items[0];
        }
        /// <summary>
        /// 克隆项目
        /// </summary>
        /// <returns></returns>
        private List<MemberAccessPermissionItem> CloneItems()
        {
            List<MemberAccessPermissionItem> clonedItems = new List<MemberAccessPermissionItem>();
            foreach (MemberAccessPermissionItem item in items)
            {
                clonedItems.Add(new MemberAccessPermissionItem(item));
            }
            return clonedItems;
        }
        public MemberAccessPermission() { }

        /// <summary>
        /// 构造,默认给予权限
        /// </summary>
        /// <param name="objectType">哪个类</param>
        /// <param name="memberName">哪个成员</param>
        /// <param name="operation">何种操作</param>
        public MemberAccessPermission(Type objectType, string memberName, MemberOperation operation)
            : this(objectType, memberName, operation, ObjectAccessModifier.Allow)
        {
        }

        /// <summary>
        /// 构造
        /// </summary>
        /// <param name="objectType">哪个类</param>
        /// <param name="memberName">哪个成员</param>
        /// <param name="operation">何种操作</param>
        /// <param name="modifier">权限</param>
        public MemberAccessPermission(Type objectType, string memberName, MemberOperation operation, ObjectAccessModifier modifier)
        {
            this.ObjectType = objectType;
            this.MemberName = memberName;
            this.Operation = operation;
            this.Modifier = modifier;
        }
        /// <summary>
        /// 联合，应该是供系统使用的，将本权限的内容与所有的合并
        /// </summary>
        /// <param name="target">将本类中的内容与目标中的合并</param>
        /// <returns>返回的集合</returns>
        public override System.Security.IPermission Union(System.Security.IPermission target)
        {
            MemberAccessPermission result = (MemberAccessPermission)Copy();
            result.items.AddRange(((MemberAccessPermission)target).CloneItems());
            return result;
        }
        /// <summary>
        /// 是否有相交的部分，重复设置的
        /// </summary>
        /// <param name="target"></param>
        /// <returns></returns>
        public override bool IsSubsetOf(System.Security.IPermission target)
        {
            if (base.IsSubsetOf(target))
            {
                foreach (MemberAccessPermissionItem targetItem in ((MemberAccessPermission)target).items)
                {
                    if (targetItem.ObjectType == ObjectType
                        && targetItem.MemberName == MemberName
                        && targetItem.Operation == Operation)
                    {
                        return targetItem.Modifier == Modifier;
                    }
                }
                return true;
            }
            return false;
        }

        [TypeConverter(typeof(PermissionTargetBusinessClassListConverter))]
        public Type ObjectType
        {
            get { return GetDesignModeItem().ObjectType; }
            set { GetDesignModeItem().ObjectType = value; }
        }

        public string MemberName
        {
            get { return GetDesignModeItem().MemberName; }
            set { GetDesignModeItem().MemberName = value; }
        }

        public MemberOperation Operation
        {
            get { return GetDesignModeItem().Operation; }
            set { GetDesignModeItem().Operation = value; }
        }

        public ObjectAccessModifier Modifier
        {
            get { return GetDesignModeItem().Modifier; }
            set { GetDesignModeItem().Modifier = value; }
        }
        /// <summary>
        /// 保存成为XML
        /// </summary>
        /// <returns></returns>
        public override System.Security.SecurityElement ToXml()
        {
            SecurityElement result = base.ToXml();
            SecurityElement itemElement = new SecurityElement("MemberAccessPermissionItem");
            itemElement.AddAttribute("Operation", Operation.ToString());
            itemElement.AddAttribute("ObjectType", (ObjectType != null) ? ObjectType.ToString() : "");
            itemElement.AddAttribute("Modifier", Modifier.ToString());
            itemElement.AddAttribute("MemberName", MemberName.ToString());
            result.AddChild(itemElement);
            return result;
        }
        /// <summary>
        /// 从XML转为对象
        /// </summary>
        /// <param name="element"></param>
        public override void FromXml(System.Security.SecurityElement element)
        {
            items.Clear();
            if (element.Children != null)
            {
                if (element.Children.Count != 1)
                {
                    throw new InvalidOperationException();
                }
                SecurityElement childElement = (SecurityElement)element.Children[0];
                ObjectType = ReflectionHelper.FindType(childElement.Attributes["ObjectType"].ToString());
                Operation = (MemberOperation)Enum.Parse(typeof(MemberOperation), childElement.Attributes["Operation"].ToString());
                Modifier = (ObjectAccessModifier)Enum.Parse(typeof(ObjectAccessModifier), childElement.Attributes["Modifier"].ToString());
                MemberName = childElement.Attributes["MemberName"].ToString();
            }
        }

        public override string ToString()
        {
            return ((ObjectType != null) ? ObjectType.Name : "N/A") + "." + MemberName + " - " + Modifier + " " + Operation;
            //return base.ToString();
        }

        /// <summary>
        /// 复制
        /// </summary>
        /// <returns></returns>
        public override System.Security.IPermission Copy()
        {
            MemberAccessPermission result = new MemberAccessPermission();
            result.items.AddRange(CloneItems());
            return result;
        }
    }

    [NonPersistent]
    public class 对象编辑权限 : PermissionBase
    {
        [TypeConverter(typeof(PermissionTargetBusinessClassListConverter))]
        public Type ObjectType { get; set; }

        public ObjectAccessModifier Modifier { get; set; }

        public 对象编辑权限()
        {
        }

        public 对象编辑权限(Type objectType, ObjectAccessModifier modifier)
        {
            this.ObjectType = objectType;
            this.Modifier = modifier;
        }

        public override IPermission Copy()
        {
            return new 对象编辑权限(this.ObjectType, Modifier);
        }

        public override void FromXml(SecurityElement element)
        {
            //items.Clear();
            if (element.Children != null)
            {
                if (element.Children.Count != 1)
                {
                    throw new InvalidOperationException();
                }
                SecurityElement childElement = (SecurityElement)element.Children[0];
                ObjectType = ReflectionHelper.FindType(childElement.Attributes["ObjectType"].ToString());
                Modifier = (ObjectAccessModifier)Enum.Parse(typeof(ObjectAccessModifier), childElement.Attributes["Modifier"].ToString());

            }
            base.FromXml(element);
        }

        public override SecurityElement ToXml()
        {
            SecurityElement result = base.ToXml();
            SecurityElement itemElement = new SecurityElement("编辑对象权限");
            itemElement.AddAttribute("ObjectType", (ObjectType != null) ? ObjectType.ToString() : "");
            itemElement.AddAttribute("Modifier", Modifier.ToString());
            result.AddChild(itemElement);
            return result;
        }

        public override string ToString()
        {
            return this.GetType().Name + " " + ((ObjectType != null) ? ObjectType.Name : "N/A") + "." + " - " + Modifier;
            //return base.ToString();
        }

        /// <summary>
        /// 联合，应该是供系统使用的，将本权限的内容与所有的合并
        /// </summary>
        /// <param name="target">将本类中的内容与目标中的合并</param>
        /// <returns>返回的集合</returns>
        public override System.Security.IPermission Union(System.Security.IPermission target)
        {
            对象编辑权限 result = (对象编辑权限)Copy();

            //result.items.AddRange(((MemberAccessPermission)target).CloneItems());
            return result;
        }
        /// <summary>
        /// 是否有相交的部分，重复设置的
        /// </summary>
        /// <param name="target"></param>
        /// <returns></returns>
        public override bool IsSubsetOf(System.Security.IPermission target)
        {
            if (base.IsSubsetOf(target))
            {
                对象编辑权限 t = target as 对象编辑权限;
                if (t.ObjectType == ObjectType)
                {
                    if (t.Modifier != Modifier)
                    {
                        Debug.Write("stop");
                    }
                    return t.Modifier == Modifier;
                }
                return true;
            }
            return false;
        }

    }
    public class MemberLevelObjectAccessComparer : ObjectAccessComparer
    {
        public override bool IsMemberReadGranted(Type requestedType, string propertyName, SecurityContextList securityContexts)
        {
            ITypeInfo typeInfo = XafTypesInfo.Instance.FindTypeInfo(requestedType);
            IMemberInfo memberInfo = typeInfo.FindMember(propertyName);
            foreach (IMemberInfo currentMemberInfo in memberInfo.GetPath())
            {
                if (!SecuritySystem.IsGranted(new MemberAccessPermission(currentMemberInfo.Owner.Type, currentMemberInfo.Name, MemberOperation.Read)))
                {
                    return false;
                }
            }
            return base.IsMemberReadGranted(requestedType, propertyName, securityContexts);
        }
        public override bool IsMemberModificationDenied(object targetObject, IMemberInfo memberInfo)
        {
            foreach (IMemberInfo currentMemberInfo in memberInfo.GetPath())
            {
                if (!SecuritySystem.IsGranted(new MemberAccessPermission(currentMemberInfo.Owner.Type, currentMemberInfo.Name, MemberOperation.Write)))
                {
                    return true;
                }
            }
            return base.IsMemberModificationDenied(targetObject, memberInfo);
        }
    }
}

